package apijson.admin.server;

import java.io.FileReader;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import zuo.biao.apijson.JSONResponse;

/**机器学习测试
 * js 的 eval 很难模拟，干脆内嵌 JavaScript 脚本来执行
 * @author Lemon
 */
public class CompareUtil {

	private static Invocable invocable;
	static {
		try {
			/*获取执行JavaScript的执行引擎*/
			ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");

			String jarPath = System.getProperty("java.class.path");//directory.getCanonicalPath();
			System.out.println("CompareUtil  static  jarPath = " + jarPath);
			int index = jarPath.lastIndexOf("/");
			System.out.println("CompareUtil  static  index = " + index); //Linux下是直接 JSONResponse.js, MacOS下是 /Users/...
			String path = index < 0 ? "JSONResponse.js" : (jarPath.substring(0, index) + "/JSONResponse.js");

			System.out.println("CompareUtil  static  path = " + path);

			engine.eval(new FileReader(path));

			System.out.println("CompareUtil  static   engine.eval >>");

			invocable = (Invocable) engine;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static JSONObject compareWithStantard(JSONObject standard, JSONObject response) throws Exception {
		System.out.println("compareWithStantard  >>  invocable = " + invocable);
		String result = (String) invocable.invokeFunction("compareFromJava", JSON.toJSONString(standard), JSON.toJSONString(response), "", true);
		System.out.println("compareWithStantard  >>  result = " + result);
		return JSON.parseObject(result);
	}

	public static JSONObject updateStandard(JSONObject standard, JSONObject response) throws Exception {
		int code = response.getIntValue(JSONResponse.KEY_CODE);
		response.remove(JSONResponse.KEY_CODE);
		try {
			String result = (String) invocable.invokeFunction("updateStandardFromJava", JSON.toJSONString(standard), JSON.toJSONString(response));

			JSONObject stdd = JSON.parseObject(result);
			stdd.put(JSONResponse.KEY_CODE, code);
			return stdd;
		} finally {
			response.put(JSONResponse.KEY_CODE, code);
		}
	}

	//	public static final String TYPE = "type";
	//	public static final String NOTNULL = "notnull";
	//	public static final String VALUE_LEVEL = "valueLevel";
	//	public static final String LENGTH_LEVEL = "lengthLevel";
	//	public static final String VALUES = "values";
	//	public static final String LENGTHS = "lengths";
	//
	//	/**测试compare: 对比 新的请求与上次请求的结果
	//	   0-相同，无颜色；
	//	   1-新增字段/新增值，绿色；
	//	   2-值改变，蓝色；
	//	   3-缺少字段/整数变小数，黄色；
	//	   4-类型/code 改变，红色；
	//	 */
	//	public static Compare compareWithStandard(JSONObject target, Object real, String folder) {
	//		folder = folder == null ? "" : folder;
	//
	//		if (target == null) {
	//			return new Compare().setPath(folder).setValue(real);
	//		}
	//
	//		log("\n\n\n\n\ncompareWithStandard <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" +
	//				" \ntarget = " + JSON.format(target) + "\n\n\nreal = " + JSON.format(real));
	//
	//		Boolean notnull = target.getBoolean("notnull");
	//		log("compareWithStandard  notnull = target.put(NOTNULL, " + notnull + " >>");
	//
	//		String type = target.getString(TYPE);
	//		log("compareWithStandard  type = target.getString(TYPE) = " + type + " >>");
	//
	//		Integer valueLevel = target.getInteger(VALUE_LEVEL);
	//		log("compareWithStandard  valueLevel = target.getInteger(VALUE_LEVEL) = " + valueLevel + " >>");
	//
	//		JSONArray values = target.getJSONArray(VALUES);
	//		log("compareWithStandard  values = target.getJSONArray(VALUES) = " + JSON.format(values) + " >>");
	//
	//		if ((values == null || values.get(0) == null) && (type == "object" || type == "array")) {
	//			if (notnull == true) { // valuesnew JSONObject(), values&new JSONObject()
	//				throw new Error("Standard 在 " + folder + " 语法错误，Object 或 JSONArray 在 notnull: true 时 values 必须为有值的数组 !");
	//			}
	//
	//			log("compareWithStandard  values == null; real " + (real == null ? "=" : "!") + "= null >> return " + (real == null ? "Compare.COMPARE_EQUAL" : "Compare.COMPARE_KEY_MORE"));
	//			return new Compare()
	//					.setCode(real == null ? Compare.COMPARE_EQUAL : Compare.COMPARE_KEY_MORE)
	//					.setMsg(real == null ? "结果正确" : "是新增的")
	//					.setPath(real == null ? "" : folder)
	//					.setValue(real);
	//		}
	//
	//		if (real == null) { //少了key
	//			log("compareWithStandard  real == null >> return " + (notnull == true ? "Compare.COMPARE_KEY_LESS" : "Compare.COMPARE_EQUAL"));
	//			return new Compare()
	//					.setCode(notnull == true ? Compare.COMPARE_KEY_LESS : Compare.COMPARE_EQUAL)
	//					.setMsg(notnull == true ? "是缺少的" : "结果正确")
	//					.setPath(notnull == true ? folder : "")
	//					.setValue(real);
	//		}
	//
	//
	//
	//		if (type != getType(real)) { //类型改变
	//			log("compareWithStandard  type != getType(real) >> return Compare.COMPARE_TYPE_CHANGE");
	//			return new Compare()
	//					.setCode(Compare.COMPARE_TYPE_CHANGE)
	//					.setMsg("不是 " + type + " 类型")
	//					.setPath(folder)
	//					.setValue(real);
	//		}
	//
	//		Compare max = new Compare()
	//				.setCode(Compare.COMPARE_EQUAL)
	//				.setMsg("结果正确")
	//				.setPath("") //导致正确时也显示 folder,
	//				.setValue(null); //导致正确时也显示  real
	//
	//		Compare each;
	//
	//		if (type == "array") { // JSONArray
	//			log("compareWithStandard  type == array >> ");
	//
	//			JSONArray r = (JSONArray) real;
	//
	//			for (int i = 0; i < r.size(); i ++) { //检查real的每一项
	//				log("compareWithStandard  for i = " + i + " >> ");
	//
	//				each = compareWithStandard(values.getJSONObject(0), r.getJSONObject(i), getAbstractPath(folder, "" + i));
	//
	//				if (max.getCode() < each.getCode()) {
	//					max = each;
	//				}
	//				if (max.getCode() >= Compare.COMPARE_TYPE_CHANGE) {
	//					log("compareWithStandard  max >= Compare.COMPARE_TYPE_CHANGE >> return max = " + max);
	//					return max;
	//				}
	//			}
	//
	//			if (max.getCode() < Compare.COMPARE_LENGTH_CHANGE
	//					&& isValueCorrect(target.getInteger(LENGTH_LEVEL), target.getJSONArray(LENGTHS), r.size()) != true) {
	//				max.setCode(Compare.COMPARE_LENGTH_CHANGE);
	//				max.setMsg("长度超出范围");
	//				max.setPath(folder);
	//				max.setValue(r.size());
	//			}
	//		}
	//		else if (type == "object") { // JSONObject
	//			log("compareWithStandard  type == object >> ");
	//
	//			JSONObject r = (JSONObject) real;
	//
	//			JSONObject first = values == null ? null : values.getJSONObject(0);
	//			List<String> tks = first == null ? new ArrayList<>() : new ArrayList<>(first.keySet());
	//			String tk;
	//			for (int i = 0; i < tks.size(); i++) { //遍历并递归下一层
	//				tk = tks.get(i);
	//				if (tk == null) {
	//					continue;
	//				}
	//				log("compareWithStandard  for tk = " + tk + " >> ");
	//
	//				each = compareWithStandard(first.getJSONObject(tk), r.get(tk), getAbstractPath(folder,  tk));
	//				if (max.getCode() < each.getCode()) {
	//					max = each;
	//				}
	//				if (max.getCode() >= Compare.COMPARE_TYPE_CHANGE) {
	//					log("compareWithStandard  max >= Compare.COMPARE_TYPE_CHANGE >> return max = " + max);
	//					return max;
	//				}
	//			}
	//
	//
	//			if (max.getCode() < Compare.COMPARE_KEY_MORE) { //多出key
	//				log("compareWithStandard  max < Compare.COMPARE_KEY_MORE >> ");
	//
	//				String[] rks = r == null ? new String[]{} : r.keySet().toArray(new String[]{});
	//
	//				for (String k : rks) {
	//					log("compareWithStandard  for k = " + k + " >> ");
	//
	//					if (k != null && tks.contains(k) == false) {
	//						log("compareWithStandard  k != null && tks.indexOf(k) < 0 >> max = Compare.COMPARE_KEY_MORE;");
	//
	//						max.setCode(Compare.COMPARE_KEY_MORE);
	//						max.setMsg("是新增的");
	//						max.setPath(getAbstractPath(folder,  k));
	//						max.setValue(r.get(k));
	//						break;
	//					}
	//				}
	//			}
	//
	//		}
	//		else { // Boolean, Number, String
	//			log("compareWithStandard  type == boolean | number | string >> ");
	//
	//			if (max.getCode() < Compare.COMPARE_VALUE_CHANGE
	//					&& isValueCorrect(valueLevel, values, real) != true) {
	//				max.setCode(Compare.COMPARE_VALUE_CHANGE);
	//				max.setMsg("值超出范围");
	//				max.setPath(folder);
	//				max.setValue(real);
	//			}
	//
	//			if (max.getCode() < Compare.COMPARE_LENGTH_CHANGE) {
	//				log("compareWithStandard  max < Compare.COMPARE_LENGTH_CHANGE >> ");
	//
	//				Integer realLength = getLength(real);
	//				log("compareWithStandard  realLength = " + realLength + " >> ");
	//
	//				if (realLength != null
	//						&& isValueCorrect(target.getInteger(LENGTH_LEVEL), target.getJSONArray(LENGTHS), realLength) != true) {
	//					max.setCode(Compare.COMPARE_LENGTH_CHANGE);
	//					max.setMsg("长度超出范围");
	//					max.setPath(folder);
	//					max.setValue(realLength);
	//				}
	//			}
	//		}
	//
	//		log("\ncompareWithStandard >> return max = " + max + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n\n\n\n\n");
	//		return max;
	//	}
	//
	//	public static String getAbstractPath(String folder, String name) {
	//		folder = folder == null ? "" : folder;
	//		name = name == null ? "" : name; //导致 0 变为 ""   name = name || "";
	//		return StringUtil.isEmpty(folder, true) ? name : folder + "/" + name;
	//	}
	//
	//	public static boolean isValueCorrect(Integer level, JSONArray target, Object real) {
	//		log("isValueCorrect  \nlevel = " + level + "; \ntarget = " + JSON.format(target)
	//		+ "\nreal = " + JSON.format(real));
	//		if (target == null) {
	//			log("isValueCorrect  target == null >>  return true;");
	//			return true;
	//		}
	//		if (level == null) {
	//			level = 0;
	//		}
	//
	//		if (level == 0) {
	//			if (target.indexOf(real) < 0) { // "keynew JSONObject()": .get(0, 1)
	//				log("isValueCorrect  target.indexOf(real) < 0 >>  return false;");
	//				return false;
	//			}
	//		}
	//		else if (level == 1) { //real <= max; real >= min
	//			if (target.get(0) != null && target.get(0) < real) {
	//				log("isValueCorrect  target.get(0) != null && target.get(0) < real >>  return false;");
	//				return false;
	//			}
	//			if (target.size() > 1 && target.get(target.size() - 1) != null && target.get(target.size() - 1) > real) {
	//				log("isValueCorrect  target.size() > 1 && target.get(target.size() - 1) != null && target.get(target.size() - 1) > real >>  return false;");
	//				return false;
	//			}
	//		}
	//		else if (level == 2) {
	//			for (int i = 0; i < target.size(); i ++) {
	//
	//				if (eval(real + target.get(i)) != true) {
	//					log("isValueCorrect  eval(" + (real + target.get(i)) + ") != true >>  return false;");
	//					return false;
	//				}
	//			}
	//		}
	//		else {
	//			//不限
	//		}
	//
	//		log("isValueCorrect >> return true;");
	//		return true;
	//	}
	//
	//	public static String getType(Object o) { //typeof new JSONArray() = "object"
	//		if (o instanceof Collection) {
	//			return "array";
	//		}
	//		if (o instanceof Boolean) {
	//			return "boolean";
	//		}
	//		if (o instanceof Number) {
	//			return "number";
	//		}
	//		if (o instanceof String) {
	//			return "string";
	//		}
	//		//		if (o instanceof JSONObject) {
	//		return "object";
	//		//		}
	//	}
	//
	//
	//	/**更新测试标准，通过原来的标准与最新的数据合并来实现
	//	 */
	//	public static JSONObject updateStandard(JSONObject target, Object real) {
	//		if (real == null) { //少了key
	//			log("updateStandard  real == null");
	//			if (target != null) { //} && target.getJSONArray(VALUES) != null && target.getJSONArray(VALUES).get(0) != null) {
	//				log("updateStandard  target != null >> target.put(NOTNULL, false;");
	//				target.put(NOTNULL, false;
	//			}
	//			log("updateStandard  return target;");
	//			return target;
	//		}
	//
	//		if (target == null) {
	//			target = new JSONObject();
	//		}
	//
	//		log("\n\n\n\n\nupdateStandard <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" +
	//				" \ntarget = " + JSON.format(target) + "\n\n\nreal = " + JSON.format(real));
	//
	//		Boolean notnull = target.getBoolean(NOTNULL);
	//		log("updateStandard  notnull = target.put(NOTNULL, " + notnull + " >>");
	//		if (notnull == null) {
	//			notnull = true;
	//			target.put(NOTNULL, notnull);
	//		}
	//
	//		String type = target.getString(TYPE);
	//		log("updateStandard  type = target.getString(TYPE) = " + type + " >>");
	//		// if (type == null) { //强制用real的类型替代
	//		type = getType(real);
	//		target.put(TYPE, type);
	//		// }
	//		log("updateStandard  type = target.getString(TYPE) = getType(real) = " + type + " >>");
	//
	//
	//		Integer lengthLevel = target.getInteger(LENGTH_LEVEL);
	//		JSONArray lengths = target.getJSONArray(LENGTHS);
	//		log("updateStandard  lengthLevel = target.getInteger(LENGTH_LEVEL) = " + lengthLevel + " >>");
	//		log("updateStandard  lengths = target.getJSONArray(LENGTHS) = " + lengths + " >>");
	//
	//
	//		Integer valueLevel = target.getInteger(VALUE_LEVEL);
	//		JSONArray values = target.getJSONArray(VALUES);
	//		log("updateStandard  valueLevel = target.getInteger(VALUE_LEVEL) = " + valueLevel + " >>");
	//		log("updateStandard  values = target.getJSONArray(VALUES) = " + JSON.format(values) + " >>");
	//
	//		if (valueLevel == null) {
	//			log("updateStandard  valueLevel == null >> valueLevel = target.getInteger(VALUE_LEVEL) = 0;");
	//			valueLevel = 0;
	//			target.put(VALUE_LEVEL, valueLevel);
	//		}
	//
	//
	//		if (type == "array") {
	//			log("updateStandard  type == array >> ");
	//
	//			JSONArray r = (JSONArray) real;
	//
	//			if (values == null) {
	//				values = new JSONArray();
	//			}
	//			if (values.get(0) == null) {
	//				values.set(0, new JSONObject());
	//			}
	//
	//			Object child = values.get(0);
	//			for (int i = 0; i < r.size(); i ++) {
	//				log("updateStandard for i = " + i + "; child = "
	//						+ JSON.format(child) + ";\n real.get(i) = "  + JSON.format(r.get(i)) + " >>");
	//
	//				child = updateStandard(child, r.get(i));
	//			}
	//			if (child == null) {
	//				log("updateStandard  child == null >> child = new JSONObject()");
	//				child = new JSONObject() //啥都确定不了，level为null默认用0替代
	//			}
	//
	//			values = new JSONArray(); 
	//			values.add(child);
	//
	//			target = setValue(target, real.size(), lengthLevel == null ? 1 : lengthLevel, lengths, true);
	//			target = setValue(target, null, valueLevel, values, false);
	//		}
	//		else if (type == "object") {
	//			log("updateStandard  type == object >> ");
	//
	//			target.getInteger(VALUE_LEVEL) = valueLevel;
	//
	//			if (values == null) {
	//				values = new JSONArray();
	//			}
	//			if (values.get(0) == null) {
	//				values.get(0) = new JSONObject();
	//			}
	//
	//			var realKeys = Object.keys(real) || new JSONArray();
	//			for(String k2 in values.get(0)) { //解决real不含k2时导致notnull不能变成false
	//				// log("updateStandard for k2 in values.get(0) = " + k2 + " >>");
	//				if (realKeys.indexOf(k2) < 0) {
	//					// log("updateStandard Object.keys(real).indexOf(k2) < 0 >> real.get(k2) = null;");
	//					real.get(k2) = null;
	//				}
	//			}
	//
	//			for(String k in real) {
	//				log("updateStandard for k in real = " + k + "; values.get(0).get(k) = "
	//						+ JSON.format(values.get(0).get(k)) + ";\n real.get(k) = "  + JSON.format(real.get(k)) + " >>");
	//				values.get(0).get(k) = updateStandard(values.get(0).get(k), real.get(k));
	//			}
	//
	//			target.getJSONArray(VALUES) = values;
	//		}
	//		else {
	//			log("updateStandard  type == other >> ");
	//
	//			if (values == null) {
	//				values = new JSONArray();
	//			}
	//			if (valueLevel < 1 && type == "number" && String(real).indexOf(".") >= 0) { //double 1.23
	//				valueLevel = 1;
	//			}
	//			target.getJSONArray(VALUES) = values;
	//
	//			target = setValue(target, getLength(real), lengthLevel == null ? 1 : lengthLevel, lengths, true);
	//			target = setValue(target, real, valueLevel, values, false);
	//		}
	//
	//		log("\nupdateStandard >> return target = " + JSON.format(target) + "\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n\n\n\n\n");
	//
	//		return target;
	//	}
	//
	//	/**
	//	 * @param target
	//	 * @param value
	//	 * @param lengthLevel 0 - new JSONArray() , 1 - min-max, 2 - "conditions", 3 - 任何值都行
	//	 * @param originLength
	//	 * @return new Compare()
	//	 */
	//	public static JSONObject setValue(JSONObject target, Object real, Integer level, Object origin, boolean isLength) {
	//		log("setValue  level = " + level + "; isLength = " + isLength
	//				+ " ;\n target = " + JSON.format(target)
	//				+ " ;\n real = " + JSON.format(real)
	//				+ " ;\n origin = " + JSON.format(origin)
	//				+  " >> ");
	//
	//		if (target == null) {
	//			target = new JSONObject();
	//		}
	//		String type = target.getString(TYPE);
	//		log("setValue  type = target.getString(TYPE) = " + type + " >> ");
	//
	//		if (level == null) {
	//			level = 0;
	//		}
	//		if (isLength != true || (type == "array" || type == "number" || type == "string")) {
	//
	//			var levelName = isLength != true ? "valueLevel" : "lengthLevel";
	//			target.get(levelName) = level;
	//			if (level >= 3) { //无限
	//				return target;
	//			}
	//			//String 类型在 长度超过一定值 或 不是 常量名 时，改成 无限模型
	//			//不用 type 判断类型，这样可以保证 lengthType 不会自动升级
	//			if (typeof real == "string" && (real.size() > 20 || StringUtil.isName(real) != true)) {
	//				if (level != 2) { //自定义模型不受影响
	//					target.get(levelName) = 3;
	//				}
	//				return target;
	//			}
	//
	//			var vals = new JSONArray();
	//
	//			if (level == 0 || level == 1) {
	//				if (origin == null) {
	//					origin = new JSONArray();
	//				}
	//				if (real != null && origin.indexOf(real) < 0) {
	//					origin.push(real);
	//				}
	//
	//				vals = origin;
	//			}
	//			else {
	//				if (real != null) {
	//					vals.push(real);
	//				}
	//			}
	//
	//			vals = vals.sort(function (x, y) { //倒序排列，一般都是用最大长度(数据count，字符串长度等)
	//				if (x < y) {
	//					return 1;
	//				}
	//				if (x > y) {
	//					return -1;
	//				}
	//				return 0;
	//			});
	//
	//			String name = isLength != true ? VALUES : LENGTHS;
	//			log("setValue  name = " + name + "; vals = " + JSON.format(vals) + " >> ");
	//
	//			switch (level) {
	//			case 0:
	//			case 1:
	//				//当 离散区间模型 可取值超过最大数量时自动转为 连续区间模型
	//				var maxCount = getMaxValueCount(type);
	//				var extraCount = maxCount <= 0 ? 0 : vals.size() - maxCount;
	//				if (extraCount > 0 && level < 1) {
	//					if (typeof real == "boolean") { //boolean 的 true 和 false 都行，说明不限
	//						if (level != 2) { //自定义模型不受影响
	//							target.get(levelName) = 3;
	//						}
	//						return target;
	//					}
	//
	//					target.get(levelName) = 1;
	//				}
	//
	//				//从中间删除多余的值
	//				while (extraCount > 0) {
	//					vals.splice(Math.ceil(vals.size()/2), 1);
	//					extraCount -= 1;
	//				}
	//				target.get(name) = vals;
	//				break;
	//			case 2: //自定义的复杂条件，一般是准确的，不会纠错
	//				// target.get(name) = (StringUtil.isEmpty(origin, true) ? "" : origin + ",")
	//				//   + ("<=" + vals.get(0) + (vals.size() <= 1 ? "" : ",>=" + vals.get(vals.size() - 1)));
	//				break;
	//			}
	//		}
	//
	//		return target;
	//	}
	//
	//	public static Integer getLength(Object value) {
	//		String type = getType(value);
	//		if (type == "array") {
	//			log("getLength  type == array >> return value.size() = " + value.size());
	//			return value.size();
	//		}
	//		if (type == "object") {
	//			log("getLength  type == object >> return null;");
	//			return null;
	//		}
	//
	//		if (type == "number") {
	//			log("getLength  type == number >> ");
	//
	//			var rs = String(value);
	//
	//			//Double 比较整数长度
	//			var index = rs.indexOf(".");
	//			if (index >= 0) {
	//				rs = rs.substring(0, index);
	//			}
	//
	//			log("getLength >> return rs.size() = " + rs.size());
	//			return rs.size()
	//		}
	//
	//		if (type == "string") {
	//			log("getLength  type == string >> return value.size() = " + value.size());
	//			return value.size()
	//		}
	//
	//		//Boolean 不需要比较长度
	//		log("getLength  type == other >> return null;");
	//		return null;
	//	}
	//
	//
	//	public static int getMaxValueCount(String type) {
	//		switch (type) {
	//		case "boolean":
	//			return 2;
	//		case "number":
	//			return 10;
	//		case "string":
	//			return 10;
	//		}
	//
	//		return 0;
	//	}
	//
	//	public static void log(String msg) {
	//		// console.log(msg);
	//	}

}
